package com.vdong.trade.trading.service.dubbo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.vdong.trade.trading.common.enums.TradeDealTypeEnum;
import com.vdong.trade.trading.common.enums.UserTypeEnum;
import com.vdong.trade.trading.common.exception.ProcessException;
import com.vdong.trade.trading.common.foundation.FoundationCRUDOperation;
import com.vdong.trade.trading.entity.dto.param.OrderTradingPramDTO;
import com.vdong.trade.trading.entity.mo.*;
import com.vdong.trade.trading.entity.po.FinanceParamDTO;
import com.vdong.trade.trading.entity.po.TransferParamDTO;
import com.vdong.trade.trading.entity.dto.TransferResultDTO;
import com.vdong.trade.trading.facade.TradingFacade;
import com.vdong.trade.trading.facade.enums.*;
import com.vdong.trade.trading.respository.TradingMOMapper;
import com.vdong.trade.trading.respository.WithdrawMOMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.lamb.framework.common.guid.LambGUIDFactory;
import org.lamb.framework.common.remote.FacadeResult;
import org.lamb.framework.common.util.FacadeResultUtils;
import org.lamb.framework.common.util.StringUtil;
import org.lamb.framework.core.annotation.LambValid;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import static com.vdong.trade.trading.common.enums.ProcessExceptionEnum.*;


@Service
@Slf4j
@com.alibaba.dubbo.config.annotation.Service
public class TradingFacadeImpl extends FoundationCRUDOperation implements TradingFacade {
    @Resource
    private LambGUIDFactory lambGUIDFactory;
    @Resource
    private TradingMOMapper tradingMOMapper;
    @Resource
    private WithdrawMOMapper withdrawMOMapper;

    @Override
    @LambValid
    @Transactional
    public String insertOrUpdateTrading(@Valid @NotNull String param) {
        log.info("insertOrUpdateTrading,入参为:[{}]", JSON.toJSONString(param));
        List<OrderMO> orderMOS = JSON.parseArray(param, OrderMO.class);
        for (OrderMO mo : orderMOS) {
            List<TradingMO> tradingMOList = tradingMOMapper.selectTradingListByParam(TradingMO
                    .builder().orderNo(mo.getOrderNo()).build());
            if (StringUtil.hasBlank(tradingMOList)) throw new ProcessException(EB00000005);
            for (TradingMO tradingMO : tradingMOList) {
                tradingMO.setSettlementStatus(SettlementStatusEnum.ALREADY_SETTLEMENT.getValue().toString());
                int row = tradingMOMapper.updateTradingById(tradingMO);
                if (row < 1) throw new ProcessException(EB000000011);
            }
        }
        return FacadeResultUtils.succFacadeBeanToString(FacadeResult.buildSucc());
    }

    @Override
    public String insertOrUpdateTransfer(@Valid @NotNull String param) {
        log.info("insertOrUpdateTransfer,入参为:[{}]", JSON.toJSONString(param));
        TransferParamDTO paramDTO = JSON.parseObject(param, TransferParamDTO.class);
        String guid = lambGUIDFactory.GUID();
        return JSON.toJSONString(operation(param, WithdrawMO.class, (e) -> {
            if (e.getId() != null) withdrawMOMapper.insertWithdraw(e);
            e.setTradingNo(guid);
            withdrawMOMapper.insertWithdraw(e);
            if (StringUtils.isBlank(e.getTradingNo())) throw new ProcessException(EB00000000);
            return JSON.toJSONString(TransferResultDTO.builder().tradeNo(e.getTradingNo()).build());
        }));
    }

    @Override
    @Transactional
    public String insertThreeTrading(String param) {
        log.info("insertThreeTrading,入参为:[{}]", param);
        OrderTradingPramDTO paramDTO = JSON.parseObject(param, OrderTradingPramDTO.class);
        if (StringUtil.hasBlank(paramDTO)) {
            return FacadeResultUtils.failFacadeBeanToString("传入参数不存在");
        }
        try {
            FacadeResult result = insertTradingMOByParam(paramDTO);
            if (!result.isSuccess()) throw new ProcessException(EB00000001);
        } catch (Exception e) {
        }
        return FacadeResultUtils.succFacadeBeanToString(FacadeResult.buildSucc());
    }

    @Override
    public String earnings(String param) {
        log.info("earnings,入参为:[{}]", JSON.toJSONString(param));
        FinanceParamDTO paramDTO = JSON.parseObject(param, FinanceParamDTO.class);
        EarningMO earningMO = tradingMOMapper.selectEarnings(paramDTO);
        return FacadeResultUtils.succFacadeBeanToString(earningMO);
    }

    @Override
    public String pusherEarnings(String param) {
        log.info("pusherEarnings,入参为:[{}]", JSON.toJSONString(param));
        FinanceParamDTO paramDTO = JSON.parseObject(param, FinanceParamDTO.class);
        PusherEarningMO earningMO = tradingMOMapper.pusherEarnings(paramDTO);
        return FacadeResultUtils.succFacadeBeanToString(earningMO);
    }

    @Transactional
    protected FacadeResult insertTradingMOByParam(OrderTradingPramDTO param) throws Exception {
        TradingMO tradingMOPusher = TradingMO.builder()
                .userId(param.getPusherId())
                .name(param.getPusherName())
                .userType(UserTypeEnum.PUSHER.getValue().toString())
                .dealType(TradeDealTypeEnum.ORDER_PUSHER_SUCCESS.getType())
                .money(param.getPusherAnticipatedIncomeAmount())
                .sysType(param.getOrderModel())
                .wechatDataId(Long.valueOf(param.getWechatDataId()))
                .orderNo(param.getOrderNo())
                .tradeType(TradeTypeEnum.ACCOUNT_ENTER.getValue().toString())
                .payType(PayTypeEnum.WECHAT_PAY.getValue().toString())
                .status(StatusEnum.STATUS_NO.getValue().toString())
                .settlementStatus(SettlementStatusEnum.NO_SETTLEMENT.getValue().toString())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        if (tradingMOMapper.insertTrading(tradingMOPusher) < 1) throw new ProcessException(EB000000012);

        TradingMO tradingMOCompany = TradingMO.builder()
                .userId(param.getCompanyId())
                .name(param.getCompanyName())
                .userType(UserTypeEnum.COMPANY.getValue().toString())
                .dealType(TradeDealTypeEnum.ORDER_PUSHER_SUCCESS.getType())
                .money(param.getPlatformAnticipatedIncomeAmount())
                .sysType(param.getOrderModel())
                .wechatDataId(Long.valueOf(param.getWechatDataId()))
                .orderNo(param.getOrderNo())
                .tradeType(TradeTypeEnum.ACCOUNT_ENTER.getValue().toString())
                .payType(PayTypeEnum.WECHAT_PAY.getValue().toString())
                .status(StatusEnum.STATUS_NO.getValue().toString())
                .settlementStatus(SettlementStatusEnum.NO_SETTLEMENT.getValue().toString())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        if (tradingMOMapper.insertTrading(tradingMOCompany) < 1) throw new ProcessException(EB000000012);

        TradingMO tradingMOMerchant = TradingMO.builder()
                .userId(param.getMerchantId())
                .name(param.getMerchantName())
                .userType(UserTypeEnum.MERCHANT.getValue().toString())
                .dealType(TradeDealTypeEnum.ORDER_PUSHER_SUCCESS.getType())
                .money(param.getProductDistributionAmount())
                .sysType(param.getOrderModel())
                .wechatDataId(Long.valueOf(param.getWechatDataId()))
                .orderNo(param.getOrderNo())
                .tradeType(TradeTypeEnum.ACCOUNT_ENTER.getValue().toString())
                .payType(PayTypeEnum.WECHAT_PAY.getValue().toString())
                .status(StatusEnum.STATUS_NO.getValue().toString())
                .settlementStatus(SettlementStatusEnum.NO_SETTLEMENT.getValue().toString())
                .createTime(new Date())
                .updateTime(new Date())
                .build();
        if (tradingMOMapper.insertTrading(tradingMOMerchant) >= 1) throw new ProcessException(EB000000012);

        return FacadeResult.buildSucc();
    }
}
